home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
akcl1615.lha
/
c
/
cmac.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-05
|
6KB
|
323 lines
#ifndef FIRSTWORD
#include "include.h"
#endif
#include "mp.h"
#include "arith.h"
#include "num_include.h"
/* I believe the instructions used here are ok for 68010.. */
#ifdef MC68K
#define MC68020
#endif
static
object *modulus;
#define FIXNUMP(x) (type_of(x)==t_fixnum)
/* Note: the modulus is guaranteed > 0 */
#define FIX_MOD(X,MOD) {register int MOD_2; \
if (X > (MOD_2=(MOD >>1))) X=X-MOD; else \
if (X < -MOD_2) X=X+MOD;}
#define MYmake_fixnum(doto,x) \
{register int CMPt1; \
doto \
((((CMPt1=(x))+1024)&-2048)==0?small_fixnum(CMPt1):make_fixnum(CMPt1));}
void siLcmod();
void siLcplus();
void siLctimes();
void siLcdifference();
object ctimes(),cplus(),cdifference(),cmod();
init_cmac()
{
/* add_symbol("ctimes",&ctimes,"cplus",&cplus,"cdifference",&cdifference,"cmod",
&cmod, 0); */
modulus = (&((make_si_special("MODULUS",Cnil))->s.s_dbind));
make_si_function("CMOD",siLcmod);
make_si_function("CPLUS",siLcplus);
make_si_function("CTIMES",siLctimes);
make_si_function("CDIFFERENCE",siLcdifference);
}
/* if hi < 0 this is taken to be the two's complement expression of
a bignum */
object
signed_bignum2(hi,lo)
int hi,lo;
{
GEN w;
object result;
long u[4];
u[0] = 0x01010004;
u[1] = 0x01010004;
u[2] = 0;
u[3] = 0;
if (hi < 0)
{ setsigne(u,-1);
if (lo > 0) /* no borrow */
{ lo = -lo;
hi = -hi;}
else {hi -= 1;
hi = -hi;}
}
else
if (hi > 0)
{setsigne(u,1);
}
else /*hi==0 */
{ setsigne(u,1);
setlgef(u,3);
MP_LOW(u,3) = lo;
result = make_integer(u);
setlgef(u,4);
return result;}
/* its length 4 */
MP_START_LOW(w,u,4);
MP_NEXT_UP(w) = lo;
MP_NEXT_UP(w) = hi;
return(make_integer(u));
}
#ifdef MC68020
/*
int
dblrem(m,n,mod)
int m,n,mod;
{ asm("movl a6@(8),d1");
asm("mulsl a6@(12),d0:d1");
asm("divsl a6@(16),d0:d1");
}
*/
#endif
object make_integer();
static unsigned long small_pos_int[3]={0x1000003,0x01000003,0};
static unsigned long small_neg_int[3]={0x1000003,0xff000003,0};
static unsigned long s4_neg_int[4]={0x1000004,0xff000004,1,0};
object
fplus(a,b)
int a,b;
{ int z ;
int x;
if (a >= 0)
{ if (b >= 0)
{ x = a + b;
if (x == 0) return small_fixnum(0);
small_pos_int[2]=x;
return make_integer(small_pos_int);
}
else
{ /* b neg */
x = a + b;
MYmake_fixnum(return,x);
}}
else
{ /* a neg */
if (b >= 0)
{ x = a + b;
MYmake_fixnum(return,x);
}
else
{ /* both neg */
{ unsigned long Xtx,Xty,overflow,Xtres;
Xtres = addll(-a,-b);
if (overflow)
{
s4_neg_int[3]=Xtres;
return make_integer(s4_neg_int);}
else
{ small_neg_int[2]=Xtres;
return make_integer(small_neg_int);}
}}}
}
object
fminus(a,b)
int a,b;
{ int z ;
int x;
if (a >= 0)
{ if (b >= 0)
{ x = a - b;
MYmake_fixnum(return,x);
}
else
{ /* b neg */
x = a - b;
if (x==0) return small_fixnum(0);
small_pos_int[2]=x;
return make_integer(small_pos_int);
}}
else
{ /* a neg */
if (b <= 0)
{ x = a - b;
MYmake_fixnum(return,x);
}
else
{ /* b positive */
{ unsigned long Xtx,Xty,overflow,Xtres;
unsigned long t[4];
Xtres = addll(-a,b);
if (overflow)
{ s4_neg_int[3]=Xtres;
return make_integer(s4_neg_int);}
else
{ small_neg_int[2]=Xtres;
return make_integer(small_neg_int);}
}}}
}
#define our_minus(a,b) ((FIXNUMP(a)&&FIXNUMP(b))?fminus(fix(a),fix(b)): \
number_minus(a,b))
#define our_plus(a,b) ((FIXNUMP(a)&&FIXNUMP(b))?fplus(fix(a),fix(b)): \
number_plus(a,b))
#define our_times(a,b) number_times(a,b)
int
dblrem(a,b,mod)
int a,b,mod;
{int h,l,sign;
if (a<0)
{a= -a; sign= (b<0)? (b= -b,1) :-1;}
else { sign= (b<0) ? (b= -b,-1) : 1;}
l = mulul(a,b,h);
b = divul(l,mod,h);
return ((sign<0) ? -h :h);}
object
cmod(x)
object x;
{register object mod = *modulus;
if (mod==Cnil) return(x);
else
if((type_of(mod)==t_fixnum && type_of(x)==t_fixnum))
{register int xx,mm;
mm=fix(mod);
if (mm==2) {xx= (fix(x) & 1); return(small_fixnum(xx));}
xx=(fix(x)%mm);
FIX_MOD(xx,mm);
MYmake_fixnum(return,xx);
}
else
{object qp,rp,mod2;
int compare;
integer_quotient_remainder_1(x,mod,&qp,&rp);
mod2=shift_integer(mod,-1);
compare = number_compare(rp,small_fixnum(0));
if (compare >= 0)
{compare=number_compare(rp,mod2);
if (compare > 0) rp=number_minus(rp,mod);}
else
if (number_compare(number_negate(mod2), rp) > 0)
{rp = number_plus(rp,mod);}
return rp;}}
object
ctimes(a,b)
object a,b;
{object mod = *modulus;
if (FIXNUMP(mod))
{register int res, m ;
res=dblrem(fix(a),fix(b),m=fix(mod));
FIX_MOD(res,m);
MYmake_fixnum(return,res);}
else if (mod==Cnil)
{ return(our_times(a,b));}
return cmod(number_times(a,b));}
object
cdifference(a,b)
object a,b;
{object mod = *modulus;
if (FIXNUMP(mod))
{register int res,m;
res=((fix(a)-fix(b))%(m=fix(mod)));
FIX_MOD(res,m);
MYmake_fixnum(return,res);}
else if (mod==Cnil)
return (our_minus(a,b));
else return(cmod(number_minus(a,b)));}
object
cplus(a,b)
object a,b;
{object mod = *modulus;
if (FIXNUMP(mod))
{register int res,m;
res=((fix(a)+fix(b))%(m=fix(mod)));
FIX_MOD(res,m);
MYmake_fixnum(return,res);}
else
if (mod==Cnil)
return (our_plus(a,b));
else
return(cmod(number_plus(a,b)));}
void
siLcmod()
{check_arg(1);
vs_base[0]=cmod(vs_base[0]);
}
void
siLcplus()
{register object *base;
base=vs_base;
check_arg(2);
base[0]=cplus(base[0],base[1]);
vs_top=base+1;
}
void
siLctimes()
{register object *base;
base=vs_base;
check_arg(2);
base[0]=ctimes(base[0],base[1]);
vs_top=base+1;
}
void
siLcdifference()
{register object *base;
base=vs_base;
check_arg(2);
base[0]=cdifference(base[0],base[1]);
vs_top=base+1;
}
object
memq(a,b)
register object a,b;
{while (1)
{if ((a==b->c.c_car)||b==Cnil) return b;
b=b->c.c_cdr;}}